/**
 * @filename:ProorderServiceImpl Dec 22, 2023
 * @project Wonder Vue Admin Api  1.1.0
 * Copyright(c) 2022 Wonder Co. Ltd.
 * All right reserved.
 */
package com.wonder.app.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.utils.VtuzxUtil;
import com.wonder.admin.service.IVtuzxKingdeeService;
import com.wonder.app.domain.*;
import com.wonder.app.mapper.*;
import com.wonder.app.service.*;
import com.wonder.app.request.ProorderRequest;
import com.wonder.bean.kingdee.VtuzxKingdeeCloudClient;
import com.wonder.bean.kingdee.xqc.VtuzxArrayList;
import com.wonder.common.utils.DateUtils;
import com.wonder.common.utils.StringUtils;
import com.wonder.common.utils.MessageUtils;
import com.wonder.common.common.AjaxResult;

import java.util.*;

import com.wonder.constant.BillType;
import com.wonder.constant.IXqcConst;
import com.wonder.netty.BootNettyChannelInboundHandlerAdapter;
import jnr.constants.platform.PRIO;
import jnr.ffi.annotations.In;
import org.bouncycastle.asn1.cmp.OOBCertHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

/**
 * @Description:TODO(生产订单服务实现)
 *
 * @version: 1.1.0
 * @author: Wonder
 *
 */
@Service
public class ProorderServiceImpl  extends ServiceImpl<ProorderDao, Proorder> implements ProorderService  {

	@Autowired
	private ProorderDao proorderDao;

	@Autowired
	private ProorderlistDao proorderlistDao;

	@Autowired
	private PrdTaskQtyDao prdTaskQtyDao;

	@Autowired
	private ProorderService proorderService;

	@Autowired
	private ProppbomlistDao proppbomlistDao;

	@Autowired
	private ProppbomlistService proppbomlistService;

	@Autowired
	private PrdTaskQtyService prdTaskQtyService;

	@Autowired
	private IVtuzxKingdeeService kingdeeService;

	@Autowired
	private MaterialDao materialDao;

	@Autowired
	private ProorderlistService proorderlistService;

	@Autowired
	private ProppbomDao proppbomDao;

	@Autowired
	private ProppbomService proppbomService;

	@Autowired
	private ScanDao scanDao;

	@Autowired
	private ScanService scanService;

	@Autowired
	private InStockDao inStockDao;

	@Autowired
	private InStockDetailDao inStockDetailDao;

	@Autowired
	private InStockService inStockService;

	@Autowired
	private InStockDetailService inStockDetailService;

	/**
	 * 验证生产订单信息
	 *
	 * @param proorder
	 * @param type
	 * @return String
	 */
	@Override
	public String validate(Proorder proorder,String type){


		return "";
	}


	/**
	 * Description:生产订单分页返回
	 * @param request //检索条件
	 * @param page //分页参数
	 * @return IPage<Proorder>   //分页记录
	 */
	@Override
	public IPage<Proorder> selectList(ProorderRequest request, Page<Proorder> page){
		LambdaQueryWrapper<Proorder> lambdaQueryWrapper = new LambdaQueryWrapper<>();

		if (null != request.getId()) {
			lambdaQueryWrapper.eq(Proorder::getId, request.getId());
		}

		if (StringUtils.hasText(request.getBillNo())) {
			lambdaQueryWrapper.like(Proorder::getBillNo, request.getBillNo());
		}

		if (StringUtils.hasText(request.getType())) {
			lambdaQueryWrapper.eq(Proorder::getType, request.getType());
		}

		if (request.getCreateTime() != null){
			Date[] createTime=request.getCreateTime();
			if(createTime.length>0)
				lambdaQueryWrapper.ge(Proorder::getCreateTime, createTime[0]);
			if(createTime.length==2)
				lambdaQueryWrapper.le(Proorder::getCreateTime,DateUtils.dateToStr(createTime[1],"yyyy-MM-dd")+ " 23:59:59");

		}

		if (StringUtils.hasText(request.getPlanner())) {
			lambdaQueryWrapper.like(Proorder::getPlanner, request.getPlanner());
		}


		lambdaQueryWrapper.orderByDesc(Proorder::getId);
		Page<Proorder> selectPage = this.baseMapper.selectPage(page, lambdaQueryWrapper);
		return selectPage;
	}

	@Override
	public VtuzxMap getProorderDetail(String billNo) {
		VtuzxMap data = new VtuzxMap();
		Proorder proorder = proorderDao.selectOne(new QueryWrapper<Proorder>().eq("billNo",billNo));
		List<Proorderlist> proorderList = proorderlistDao.selectList(new QueryWrapper<Proorderlist>().eq("billNo",billNo));
		List<PrdTaskQty> taskQtyList = prdTaskQtyDao.selectList(new QueryWrapper<PrdTaskQty>().eq("taskBillNo",billNo));

		String materialNo = proorderList.get(0).getMaterialNo();
		//查询当前物料是否启用保质期和批号
		Material material = materialDao.selectOne(new LambdaQueryWrapper<Material>().eq(Material::getFNUMBER, materialNo));
		Boolean isFlot = material.getFIsFlot();
		Boolean isProduce = material.getFIsProduce();
		data.append("header",proorder)
				.append("dataList",proorderList)
				.append("userList",taskQtyList)
				.append("isFlot",isFlot)
				.append("isProduce",isProduce);

		return data;
	}

	@Override
	public boolean unAuditProorder(String userName, Long id) {
		Proorder proorder = proorderDao.selectById(id);
		proorder.setUpdateTime(new DateTime());
		proorder.setUpdateUserName(userName);
		proorder.setStatus("save");
		boolean isSuccess = proorderService.updateById(proorder);
		return isSuccess;
	}

	@Override
	public boolean auditProorder(String userName, Long id) {
		Proorder proorder = proorderDao.selectById(id);
		proorder.setUpdateTime(new DateTime());
		proorder.setUpdateUserName(userName);
		proorder.setAuditTime(new DateTime());
		proorder.setAuditUserName(userName);
		proorder.setStatus("audit");
		boolean isSuccess = proorderService.updateById(proorder);
		return isSuccess;
	}

	@Override
	public List<Map<String, Object>> getPickMaterialByTask(JSONObject map) {
		JSONArray taskList = (JSONArray) map.getObj("taskList");
		if (taskList == null || taskList.size() == 0){
			return  null;
		}
		List<String> materialNoList = new ArrayList<>();
		List<Proppbomlist> proppbomlists = proppbomlistDao.selectList(new QueryWrapper<Proppbomlist>().in("taskBillNo", taskList));
		Map<String,Object> data = new HashMap<>();
		List<Map<String,Object>> dataLsit = new ArrayList<>();
		for (Proppbomlist proppbomlist : proppbomlists) {
			String materialNo = proppbomlist.getMaterialNo();
			if (!materialNoList.contains(materialNo)){
				materialNoList.add(materialNo);
			}
			double needQty = proppbomlist.getNeedQty();//需求数量
			double dataQty = VtuzxUtil.getDouble(data,materialNo);
			if (dataQty > 0){//如果有此物料
				data.put(materialNo,needQty + dataQty);
			} else {
				data.put(materialNo,needQty );
				String materialName = proppbomlist.getMaterialName();
				String specification = proppbomlist.getSpecification();
				String unit = proppbomlist.getUnit();
				Map<String,Object> material = new HashMap<>();
				material.put("materialNo",materialNo);
				material.put("materialName",materialName);
				material.put("specification",specification);
				material.put("unit",unit);
				dataLsit.add(material);
			}
		}

		//循环添加物料重量信息
		for (Map<String, Object> dataMap : dataLsit) {
			String materialNo = dataMap.get("materialNo").toString();
			Double count = (Double) data.get(materialNo);
			dataMap.put("count",count);
		}
		//查询物料的基本仓库
		List<Material> materials = materialDao.selectList(new LambdaQueryWrapper<Material>()
				.in(Material::getFNUMBER, materialNoList));
		//添加仓库信息
		for (Map<String, Object> dataMap : dataLsit) {
			String materialNo = dataMap.get("materialNo").toString();
			for (Material material : materials){
				String materialFnumber = material.getFNUMBER();
				String stockNo = material.getStockNo();
				String stockName = material.getStockName();
				if (materialNo.equals(materialFnumber)){
					dataMap.put("stockNo",stockNo);
					dataMap.put("stockName",stockName);
				}
			}
		}
		return dataLsit;
	}

	@Override
	public Boolean prdTaskStart(JSONObject map) {
		//订单号是多个
		String taskBillNos = map.getStr("taskBillNo");
		String[] billNoList = taskBillNos.split(",");
		JSONArray users = map.getJSONArray("users");
		List<PrdTaskQty> taskList = new ArrayList<>();
		//循环添加信息
		for (String billNo : billNoList){
			//循环判断用户信息
			for (int i = 0;i < users.size(); i++ ) {
				JSONObject jsonObject = users.getJSONObject(i);
				Integer userId = jsonObject.getInt("userId");
				String userName = jsonObject.getStr("userName");
				String workType = jsonObject.getStr("workType");
				boolean isCold = jsonObject.getBool("isColdStock");
				String fWork = jsonObject.getStr("fWork");

				//先查询当前任务是否有该员工的工时信息
				PrdTaskQty taskQty = prdTaskQtyDao.selectOne(new QueryWrapper<PrdTaskQty>()
						.eq("taskBillNo",billNo)
						.eq("userId",userId));
				//如果有该员工的信息修改一下开工时间
				if (null != taskQty){
					taskQty.setUserid(userId);
					taskQty.setUserName(userName);
					taskQty.setWorkType(workType);
					taskQty.setIsColdStock(isCold);
					taskQty.setFwork(fWork);
					taskQty.setStartDate(new Date());//开始时间取当前时间
					taskList.add(taskQty);
				} else {
					//如果没有该员工的信息添加新的数据
					//查询物料表获取物料计件信息
					Proorderlist orderDetail = proorderlistDao.selectOne(new QueryWrapper<Proorderlist>().eq("billNo", billNo));
					String materialNo = orderDetail.getMaterialNo();
					Material material = materialDao.selectOne(new QueryWrapper<Material>().eq("FNumber", materialNo));
					Double fCoefficient = material.getFCoefficient();//分配系数
					String materialName = material.getFName();
					String unit = material.getUnit();
					Double price = material.getPrice();//产品计件单价
					PrdTaskQty prdTaskQty = new PrdTaskQty();
					prdTaskQty.setTaskBillNo(billNo);
					prdTaskQty.setUserid(userId);
					prdTaskQty.setUserName(userName);
					prdTaskQty.setWorkType(workType);
					prdTaskQty.setIsColdStock(isCold);
					prdTaskQty.setUserProportion(fCoefficient);
					prdTaskQty.setFwork(fWork);
					prdTaskQty.setMaterialNo(materialNo);
					prdTaskQty.setMaterialName(materialName);
					prdTaskQty.setUnit(unit);
					prdTaskQty.setPrice(price);
					prdTaskQty.setStartDate(new Date());//开始时间取当前时间
					taskList.add(prdTaskQty);
				}

			}

		}
		//添加员工信息数据
		boolean res = prdTaskQtyService.saveOrUpdateBatch(taskList);
		//修改订单的状态
		List<Proorder> proorderList = proorderDao.selectList(new QueryWrapper<Proorder>().in("billNo", billNoList));
		for (Proorder proorder : proorderList){
			proorder.setBasiessStatus("start");
		}
		boolean proRes = proorderService.updateBatchById(proorderList);

		return res && proRes;
	}

	@Override
	public Boolean prdTaskStop(JSONObject map) throws Exception {
		String taskBillNo = map.getStr("taskBillNo");
		String userIds = map.getStr("userId");
		String[] userList = userIds.split(",");
		List<PrdTaskQty> taskQtyList = new ArrayList<>();
		for (String idStr : userList ){
			long userId = Long.parseLong(idStr);
			//判断员工是否开工
			PrdTaskQty taskQty = prdTaskQtyDao.selectOne(new QueryWrapper<PrdTaskQty>()
					.eq("taskBillNo",taskBillNo)
					.eq("userId",userId));
			if (null == taskQty){
				throw new Exception(String.format("员工id:%d,未在当前任务开工,无法暂停",userId));
			}
			Date startDate = taskQty.getStartDate();//开工时间

			//获取开工时间和结束时间相差的分钟数
			Long minutes = DateUtils.getDatePoorMinutes(new Date(), startDate);
			taskQty.setEndDate(new Date());

			Long workTime = taskQty.getWorkTime();
			//判断之前工时字段是否有值
			if(null == workTime){
				taskQty.setWorkTime(minutes);
			} else {//当前工时加上之前已有的工时
				taskQty.setWorkTime(workTime +minutes);
			}
			taskQtyList.add(taskQty);


		}
		boolean b = prdTaskQtyService.updateBatchById(taskQtyList);
		//修改任务状态为暂停
		Proorder proorder = proorderDao.selectOne(new QueryWrapper<Proorder>().eq("billNo", taskBillNo));
		proorder.setBasiessStatus("stop");
		boolean res = proorderService.updateById(proorder);

		return res && b;
	}

	@Override
	public Boolean prdTaskEnd(JSONObject map) throws Exception{
		String taskBillNo = map.getStr("taskBillNo");
		String userIds = map.getStr("userId");
		String[] userList = userIds.split(",");
		List<PrdTaskQty> taskQtyList = new ArrayList<>();
		for (String idStr : userList ){
			long userId = Long.parseLong(idStr);
			//判断员工是否开工
			PrdTaskQty taskQty = prdTaskQtyDao.selectOne(new QueryWrapper<PrdTaskQty>()
					.eq("taskBillNo",taskBillNo)
					.eq("userId",userId));
			if (null == taskQty){
				throw new Exception(String.format("员工id:%d,未在当前任务开工,无法暂停",userId));
			}
			Date startDate = taskQty.getStartDate();//开工时间

			//获取开工时间和结束时间相差的分钟数
			Long minutes = DateUtils.getDatePoorMinutes(new Date(), startDate);
			taskQty.setEndDate(new Date());

			Long workTime = taskQty.getWorkTime();
			//判断之前工时字段是否有值
			if(null == workTime){
				taskQty.setWorkTime(minutes);
			} else {//当前工时加上之前已有的工时
				taskQty.setWorkTime(workTime +minutes);
			}
			taskQtyList.add(taskQty);


		}
		boolean b = prdTaskQtyService.updateBatchById(taskQtyList);
		//修改任务状态为结束
		Proorder proorder = proorderDao.selectOne(new QueryWrapper<Proorder>().eq("billNo", taskBillNo));
		proorder.setBasiessStatus("end");
		boolean res = proorderService.updateById(proorder);

		return res && b;
	}

	@Override
	public void syncProOrder(String endTime) throws Exception{
		syncProOrder(0,50,endTime);
	}

	@Override
	public Map<String, Object> getProOrderListPda(Map<String, Object> map) {
		int pageIndex = VtuzxUtil.getInt(map,"pageIndex");
		int pageSize = VtuzxUtil.getInt(map,"pageSize");
		String billNo = VtuzxUtil.getString(map,"billNo");
		LambdaQueryWrapper<Proorder> queryWrapper = new LambdaQueryWrapper<>();
		if (!VtuzxUtil.isEmpty(billNo)){
			queryWrapper.like(Proorder::getBillNo,billNo);
		}
		Page<Proorder> page = new Page<>();
		page.setSize(pageSize);
		page.setCurrent(pageIndex);
		Page<Proorder> proorderPage = proorderDao.selectPage(page, queryWrapper);

		Map<String,Object> data = new HashMap<>();
		data.put("data",proorderPage.getRecords());
		return data;
	}

	@Override
	public Map<String, Object> getProOrderList(int pageIndex, int pageSize,String startTime,String endTime,String taskBillNo) {

		//List<Proorder> dataList = proorderDao.getProOrderList(pageSize,pageIndex * pageSize,startTime,endTime);
		LambdaQueryWrapper<Proorder> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		Page<Proorder> page = new Page<>();
		page.setSize(pageSize);
		page.setPages(pageIndex);

		if (startTime != null && null != endTime){
			lambdaQueryWrapper.ge(Proorder::getCreateTime, startTime);
			lambdaQueryWrapper.le(Proorder::getCreateTime,endTime);
		}
		if(!VtuzxUtil.isEmpty(taskBillNo)){
			lambdaQueryWrapper.like(Proorder::getBillNo,taskBillNo);
		}
		lambdaQueryWrapper.orderByDesc(Proorder::getId);
		Page<Proorder> selectPage = this.baseMapper.selectPage(page, lambdaQueryWrapper);
		List<Proorder> records = selectPage.getRecords();
		List<String> billNoList = new ArrayList<>();
		for (Proorder proorder : records){
			String billNo = proorder.getBillNo();
			if (!billNoList.contains(billNo)){
				billNoList.add(billNo);
			}
		}
		List<Proorderlist> detailList = proorderlistDao.selectList(new LambdaQueryWrapper<Proorderlist>()
				.in(Proorderlist::getBillNo,billNoList));
		Map<String,Object> detailMap = new HashMap<>();
		for (Proorderlist proorderlist : detailList){
			String billNo = proorderlist.getBillNo();
			List<Proorderlist> mapValue = (List<Proorderlist>) detailMap.get(billNo);
			if (null == mapValue){
				List<Proorderlist> orderListValue = new ArrayList<>();
				orderListValue.add(proorderlist);
				detailMap.put(billNo,orderListValue);
			} else {
				mapValue.add(proorderlist);
				detailMap.put(billNo,mapValue);
			}
		}
		for (Proorder proorder : records){
			String billNo = proorder.getBillNo();
			List<Proorderlist> proorderlists = (List<Proorderlist>) detailMap.get(billNo);
			proorder.setProorderlist(proorderlists);
		}

		Map<String,Object> data = new HashMap<>();
		data.put("data",records);
		return data;
	}

	@Override
	public Map<String, Object> getProBom(String taskBillNo) {
		Proppbom proppbom = proppbomDao.selectOne(new LambdaQueryWrapper<Proppbom>().eq(Proppbom::getTaskBillNo, taskBillNo));
		List<Proppbomlist> proppbomlists = proppbomlistDao.selectList(new LambdaQueryWrapper<Proppbomlist>()
				.eq(Proppbomlist::getTaskBillNo, taskBillNo));
		Map<String,Object> data = new HashMap<>();
		data.put("header",proppbom);
		data.put("dataList",proppbomlists);
		return data;
	}

	@Override
	public Map<String,Object> startScanCode(Map<String, Object> map) {
		String billNo = map.get("billNo").toString();
		//添加任务的扫码开始时间
		Proorder proorder = proorderDao.selectOne(new LambdaQueryWrapper<Proorder>().eq(Proorder::getBillNo, billNo));
		proorder.setScanTime(new Date());
		proorderDao.updateById(proorder);
		Map<String,Object> data = new HashMap<>();
		data.put("data",proorder);
		return data;
	}

	@Override
	public Map<String,Object> getScanCode(Map<String, Object> map) {
		String scanTime = map.get("scanTime").toString();
		LambdaQueryWrapper<Scan> wrapper = new LambdaQueryWrapper<>();
		wrapper.gt(Scan::getCreateTime,scanTime);
		List<Scan> scanList = scanDao.selectList(wrapper);
		Map<String,Object> data = new HashMap<>();
		data.put("data",scanList);
		return data;
	}

	@Override
	public Map<String, Object> getUserByBillNo(String billNo) {
		LambdaQueryWrapper<PrdTaskQty> wrapper = new LambdaQueryWrapper();
		wrapper.select(PrdTaskQty::getUserid,PrdTaskQty::getUserName);
		wrapper.eq(PrdTaskQty::getTaskBillNo,billNo);
		List<PrdTaskQty> taskQtyList = prdTaskQtyDao.selectList(wrapper);
		Map<String,Object> data = new HashMap<>();
		data.put("data",taskQtyList);
		return data;
	}

	@Override
	public Boolean endScanCode(Long userId,String userName,String taskBillNo, String startTime,String produceDate,String batchNo) {
		//传送带结束扫码后查询追溯码创建时间在扫码开始时间到结束时间的追溯信息
		//添加扫码结束时间信息
//		Proorder proorder = proorderDao.selectOne(new QueryWrapper<Proorder>().eq("billNo", taskBillNo));
//		proorder.setScanEndTime(new Date());
//		proorderDao.updateById(proorder);
		List<String> trayList = BootNettyChannelInboundHandlerAdapter.msgList;
		//绑定追溯码的任务单号
//		String endTime = DateUtils.dateToStr(new Date(),"yyyy-MM-dd HH:mm:ss");
//		LambdaQueryWrapper<Scan> wrapper = new LambdaQueryWrapper<>();
//		wrapper.gt(Scan::getCreateTime,startTime).lt(Scan::getCreateTime,endTime);
//		List<Scan> scanList = scanDao.selectList(wrapper);
		String billNo = IXqcConst.createBillNo(BillType.SCRK);
		List<Scan> scanList = scanDao.selectList(new LambdaQueryWrapper<Scan>().in(Scan::getTrayNum, trayList));
		for (Scan scan : scanList){
			scan.setTaskBillNo(taskBillNo);
			scan.setInStockNo(billNo);
		}
		boolean res = scanService.updateBatchById(scanList);

		//生成入库单
		saveInStock(userId,userName,taskBillNo,scanList.size(),billNo,produceDate,batchNo);
		//计算员工的计件数量
		//完成任务清空队列
		calculateUserCount(userId,userName,taskBillNo,scanList.size(),billNo);
		BootNettyChannelInboundHandlerAdapter.msgList.clear();
		return res;
	}

	@Override
	public Boolean inStockPda(Long userId,String userName,Map<String, Object> header,  String produceDate) {
		String taskBillNo = header.get("billNo").toString();
		Double count = Double.parseDouble(header.get("count").toString());
		String billNo = IXqcConst.createBillNo(BillType.SCRK);
		String batchNo = header.get("batchNo").toString();
		Boolean  res = saveInStock(userId,userName,taskBillNo, count, billNo, produceDate, batchNo);
		return res;
	}

	@Override
	public Boolean updateWorkTime(List<PrdTaskQty> entity) {

		return null;
	}

	@Override
	public Boolean prdTaskStopAll(JSONObject map) throws Exception{
		String taskBillNo = map.getStr("taskBillNo");

		List<PrdTaskQty> taskQtyList = prdTaskQtyDao.selectList(new LambdaQueryWrapper<PrdTaskQty>()
				.eq(PrdTaskQty::getTaskBillNo,taskBillNo));
		for (PrdTaskQty taskQty : taskQtyList ){

			Date startDate = taskQty.getStartDate();//开工时间

			//获取开工时间和结束时间相差的分钟数
			Long minutes = DateUtils.getDatePoorMinutes(new Date(), startDate);
			taskQty.setEndDate(new Date());

			Long workTime = taskQty.getWorkTime();//工时
			//判断之前工时字段是否有值
			if(null == workTime){
				taskQty.setWorkTime(minutes);
			} else {//当前工时加上之前已有的工时
				taskQty.setWorkTime(workTime +minutes);
			}
			taskQtyList.add(taskQty);

		}
		boolean b = prdTaskQtyService.updateBatchById(taskQtyList);
		//修改任务状态为暂停
		Proorder proorder = proorderDao.selectOne(new QueryWrapper<Proorder>().eq("billNo", taskBillNo));
		proorder.setBasiessStatus("stop");
		boolean res = proorderService.updateById(proorder);

		return res && b;
	}

	@Override
	public Boolean prdTaskEndAll(JSONObject map) throws Exception {
		String taskBillNo = map.getStr("taskBillNo");

		List<PrdTaskQty> taskQtyList = prdTaskQtyDao.selectList(new LambdaQueryWrapper<PrdTaskQty>()
				.eq(PrdTaskQty::getTaskBillNo,taskBillNo));
		for (PrdTaskQty taskQty : taskQtyList ){

			Date startDate = taskQty.getStartDate();//开工时间

			//获取开工时间和结束时间相差的分钟数
			Long minutes = DateUtils.getDatePoorMinutes(new Date(), startDate);
			taskQty.setEndDate(new Date());

			Long workTime = taskQty.getWorkTime();//工时
			//判断之前工时字段是否有值
			if(null == workTime){
				taskQty.setWorkTime(minutes);
			} else {//当前工时加上之前已有的工时
				taskQty.setWorkTime(workTime +minutes);
			}
			taskQtyList.add(taskQty);

		}
		boolean b = prdTaskQtyService.updateBatchById(taskQtyList);
		//修改任务状态为结束
		Proorder proorder = proorderDao.selectOne(new QueryWrapper<Proorder>().eq("billNo", taskBillNo));
		proorder.setBasiessStatus("end");
		boolean res = proorderService.updateById(proorder);

		return res && b;
	}

	/**
	 * 生成入库单
	 */
	private Boolean saveInStock(Long userId,String userName,String taskBillNo,double count,String billNo,String produceDate,String batchNo){

		InStock inStock = new InStock();
		inStock.setBillNo(billNo);
		inStock.setStockNo("05");//先默认入到成品库
		inStock.setStatus("save");
		inStock.setCount(count);
		inStock.setQuality(false);
		inStock.setCreateUserName(userName);
		inStock.setCreateUserId(userId);

		Proorderlist proorderDetail = proorderlistDao.selectOne(new QueryWrapper<Proorderlist>().eq("billNo", taskBillNo));
		InStockDetail inStockDetail = new InStockDetail();
		inStockDetail.setMaterialNo(proorderDetail.getMaterialNo());
		inStockDetail.setBillNo(billNo);
		inStockDetail.setMaterialName(proorderDetail.getMaterialName());
		inStockDetail.setSpecification(proorderDetail.getSpecification());
		inStockDetail.setUnit(proorderDetail.getUnit());
		inStockDetail.setCount(count);
		inStockDetail.setStockNo("05");
		//判断有没有启用批次和保质期
		if (!VtuzxUtil.isEmpty(batchNo)){
			inStockDetail.setIsFlot(true);
			inStockDetail.setFlot(batchNo);
		} else {
			inStockDetail.setIsFlot(false);
		}
		if(!StringUtils.isEmpty(produceDate)){
			Date produce = DateUtils.strToDate(produceDate, "yyyy-MM-dd");//生产日期
			Material material = materialDao.selectOne(new LambdaQueryWrapper<Material>()
					.eq(Material::getFNUMBER, proorderDetail.getMaterialNo()));
			inStockDetail.setProduceDate(produce);
			inStockDetail.setIsProduce(true);
			Integer expperiod = material.getExpperiod();
			String expUnit = material.getExpUnit();
			Date date = null;
			//根据保质期单位判断添加(年,月,日)
			if(expUnit.equals("Y")){
				date = DateUtils.addYears(produce,expperiod);
			} else if (expUnit.equals("M")){
				date = DateUtils.addMonths(produce,expperiod);
			} else if (expUnit.equals("D")){
				date = DateUtils.addDays(produce,expperiod);
			}
			inStockDetail.setExpiryDate(date);
		} else {
			inStockDetail.setIsProduce(false);
		}

		inStockDao.insert(inStock);
		inStockDetailDao.insert(inStockDetail);

		return true;
	}

	/**
	 * 同步生产订单
	 * @param endTime
	 */
	private void syncProOrder(int start, int limit, String endTime)throws Exception {

		String cond = "";
		if (!VtuzxUtil.isEmpty(endTime)){
			cond = String.format("FCreateDate > '%s' or FModifyDate > '%s' and FDocumentStatus = 'C' and FPrdOrgId.fnumber = '400'" ,endTime,endTime);
		} else {
			cond = String.format("FPrdOrgId.fnumber = '%s'","400");
		}


		VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
		List<VtuzxMap> orderQuery = kingdeeService.query(client, "PRD_MO", new VtuzxArrayList<>(
						"FBillNo", //单据编号
						"FBillType.FName",//单据类型
						"FCreateDate",//创建日期
						"FPrdOrgId.FName",//生产组织
						"FWorkShopID.FName",//生产车间
						"FPlannerID.FName",//计划员
						"FModifyDate",//修改日期
						"FCreatorId.FName",//创建人
						"FMaterialId.FNumber",//物料编码
						"FMaterialName",//物料名称
						"FSpecification",//规格型号
						"FUnitId.FName",//单位
						"FPlanStartDate",//计划开工日期
						"FPlanFinishDate",//计划完工日期
						"FQty",//数量
						"FDocumentStatus",//单据状态
						"F_DLMH_ZDPC",//指定批次
						"F_DLMH_JGWC",//几锅完成
						"F_DLMH_ZDSCRQ",//指定生产日期
						"F_DLMH_GS",//归属
						"F_DLMH_CJSL",//车间数量
						"FTreeEntity_FEntryId",//entryid
						"FPPBOMENTRYID"//用料清单内码

				),
				cond, "", start, limit);
		List<Proorder> orderList = new ArrayList<>();//生产订单外层表数据
		List<Proorderlist> detailList = new ArrayList<>();//生产订单内层表数据
		List<String> billNoList = new ArrayList<>();//存储生产订单编号
		List<String> materialNoList = new ArrayList<>();//物料编码集合
		for (VtuzxMap data : orderQuery){
			String billNo = VtuzxUtil.getString(data,"FBillNo");//单据编号
			Long FentryId = VtuzxUtil.getLong(data,"FTreeEntity_FEntryId");//entryid
			double F_DLMH_CJSL = VtuzxUtil.getDouble(data,"F_DLMH_CJSL");//车间数量
			String type = VtuzxUtil.getString(data,"FBillType.FName");//单据类型
			String FCreateDate = VtuzxUtil.getString(data,"FCreateDate");//创建日期
			Date createDate = DateUtils.strToDate(FCreateDate, "yyyy-MM-dd'T'HH:mm:ss");
			String prdord = VtuzxUtil.getString(data,"FPrdOrgId.FName");//生产组织
			if ("大连妙禾食品配送有限公司".equals(prdord)){
				continue;
			}
			String workShop = VtuzxUtil.getString(data,"FWorkShopID.FName");//生产车间
			String planner = VtuzxUtil.getString(data,"FPlannerID.FName");//计划员
			String FModifyDate = VtuzxUtil.getString(data,"FModifyDate");//修改日期
			Date modifyDate = DateUtils.strToDate(FModifyDate, "yyyy-MM-dd'T'HH:mm:ss");
			String createUserName = VtuzxUtil.getString(data,"FCreatorId.FName");//创建人
			String materialNo = VtuzxUtil.getString(data,"FMaterialId.FNumber");//物料编码
			String materialName = VtuzxUtil.getString(data,"FMaterialName");//物料名称
			String specification = VtuzxUtil.getString(data,"FSpecification");//规格型号
			String unit = VtuzxUtil.getString(data,"FUnitId.FName");//单位
			String FPlanStartDate = VtuzxUtil.getString(data,"FPlanStartDate");//计划开工日期
			Date planStartDate = DateUtils.strToDate(FPlanStartDate, "yyyy-MM-dd'T'HH:mm:ss");
			String FPlanFinishDate = VtuzxUtil.getString(data,"FPlanFinishDate");//计划完工日期
			String ascription = VtuzxUtil.getString(data,"ascription");//归属
			Date planFinishDate = DateUtils.strToDate(FPlanFinishDate, "yyyy-MM-dd'T'HH:mm:ss");
			Double count = VtuzxUtil.getDouble(data,"FQty");//数量
			String batchNo = VtuzxUtil.getString(data,"F_DLMH_ZDPC");//指定批次
			String produceStr = VtuzxUtil.getString(data,"F_DLMH_ZDSCRQ");//指定生产日期
			Date produceDate = DateUtils.strToDate(produceStr, "yyyy-MM-dd'T'HH:mm:ss");
			Double batch = VtuzxUtil.getDouble(data,"F_DLMH_JGWC");//几锅完成
			String ppbomentryid = VtuzxUtil.getString(data,"FPPBOMENTRYID");//用料清单内码

			if (!materialNoList.contains(materialNo)){
				materialNoList.add(materialNo);
			}

			//判断生产订单外层表数据是否存在
			Proorder proorder = proorderDao.selectOne(new QueryWrapper<Proorder>().eq("billNo", billNo));
			if (null != proorder){//如果已经存在
				proorder.setType(type);
				proorder.setCreateTime(createDate);
				proorder.setPrdorg(prdord);
				proorder.setWorkShop(workShop);
				proorder.setPlanner(planner);
				proorder.setUpdateTime(modifyDate);
				proorder.setPbomNo(ppbomentryid);
				proorder.setStatus("audit");
				proorder.setWorkShopCount(F_DLMH_CJSL);
				orderList.add(proorder);
			} else {//如果不存在创建新的
				Proorder order = new Proorder();
				order.setBillNo(billNo);
				order.setType(type);
				order.setCreateTime(createDate);
				order.setPrdorg(prdord);
				order.setWorkShop(workShop);
				order.setPlanner(planner);
				order.setUpdateTime(modifyDate);
				order.setPbomNo(ppbomentryid);
				order.setStatus("audit");
				order.setCreateUserName(createUserName);
				//单据头会有多个，去一下重
				if (!billNoList.contains(billNo)){
					orderList.add(order);
				}

			}
			//判断生产订单物料表是否存在
			Proorderlist orderDetail = proorderlistDao.selectOne(new QueryWrapper<Proorderlist>()
					.eq("entryId", FentryId));
			if (null != orderDetail){//如果不为空
				orderDetail.setMaterialNo(materialNo);
				orderDetail.setMaterialName(materialName);
				orderDetail.setSpecification(specification);
				orderDetail.setUnit(unit);
				orderDetail.setPlanStartDate(planStartDate);
				orderDetail.setPlanFinishDate(planFinishDate);
				orderDetail.setCount(count);
				orderDetail.setBatch(batch);
				orderDetail.setBatchNo(batchNo);
				orderDetail.setSpecifyDate(produceDate);
				orderDetail.setAscription(ascription);
				detailList.add(orderDetail);
			} else {
				Proorderlist proorderlist = new Proorderlist();
				proorderlist.setBillNo(billNo);
				proorderlist.setEntryId(FentryId);
				proorderlist.setMaterialNo(materialNo);
				proorderlist.setMaterialName(materialName);
				proorderlist.setSpecification(specification);
				proorderlist.setUnit(unit);
				proorderlist.setPlanStartDate(planStartDate);
				proorderlist.setPlanFinishDate(planFinishDate);
				proorderlist.setCount(count);
				proorderlist.setBatch(batch);
				proorderlist.setBatchNo(batchNo);
				proorderlist.setSpecifyDate(produceDate);
				proorderlist.setCreateUserName(createUserName);
				proorderlist.setAscription(ascription);
				detailList.add(proorderlist);
			}

			if (!billNoList.contains(billNo)){
				billNoList.add(billNo);
			}
		}
		//查询物料表获取物料的默认仓库
		if (!VtuzxUtil.isEmpty(materialNoList)){
			List<Material> materials = materialDao.selectList(new LambdaQueryWrapper<Material>()
					.in(Material::getFNUMBER, materialNoList));
			for (Proorderlist proorderlist : detailList){
				String materialNo = proorderlist.getMaterialNo();
				for (Material material : materials){
					String materialNumber = material.getFNUMBER();
					if (materialNo.equals(materialNumber)){
						String stockNo = material.getStockNo();
						String stockName = material.getStockName();
						proorderlist.setStockNo(stockNo);
						proorderlist.setStockName(stockName);
					}
				}
			}
		}

		//添加生产订单数据
		boolean orderRes = proorderService.saveOrUpdateBatch(orderList);
		boolean detailRes = proorderlistService.saveOrUpdateBatch(detailList);
		if (orderRes && detailRes){
			//同步用料清单
			try {
				syncPbom(billNoList,detailList);
			} catch (Exception e){
				throw new Exception(e.getMessage());
			}
		}
		if (orderQuery.size() >= limit) {
			syncProOrder(start + limit, limit,endTime);
		}
	}

	/**
	 * 同步用料清单
	 * @param billNoList
	 * @throws Exception
	 */
	private void syncPbom(List<String> billNoList,List<Proorderlist> taskDetailList) throws Exception{
		String bomCond = org.springframework.util.StringUtils.collectionToDelimitedString(billNoList, ",", "'", "'");
		//根据生产订单编号查询所需同步的用料清单
		String cond = String.format("FMOBillNO in (%s)", bomCond);
		VtuzxKingdeeCloudClient client = kingdeeService.loginKingdee();
		List<VtuzxMap> bomQuery = kingdeeService.query(client, "PRD_PPBOM", new VtuzxArrayList<>(
						"FBillNo", //单据编号
						"FPrdOrgId.FName",//生产组织
						"FWorkShopID.FName",//生产车间
						"FQty",//数量
						"FMaterialID.FNumber",//物料编码
						"FMaterialName",//物料名称
						"FMaterialModel",//物料规格
						"FUnitID.FName",//单位
						"FDocumentStatus",//单据状态
						"FCreateDate",//创建日期
						"FModifyDate",//修改日期
						"FMOBillNO",//生产订单编号
						"FSrcPPBOMID",//用料清单内码
						"FMaterialID2.FNumber",//子项物料编码
						"FMaterialName1",//子项物料名称
						"FMaterialModel1",//子项规格
						"FUnitID2.FName",//子项单位
						"FNumerator",//分子
						"FDenominator",//分母
						"FFixScrapQty",//固定损耗
						"FScrapRate",//变动损耗
						"FStdQty",//标准用量
						"FNeedQty2",//需求用量
						"FMustQty",//应发数量
						"F_DLMH_JGWC",//几锅完成
						"F_DLMH_MGSL",//每锅数量
						"FNeedDate2",//需求日期
						"FBOMEntryID"//bom分录内码

				),
				cond, "", 0, 0);
		List<Proppbom> proppbomList = new ArrayList<>();
		List<Proppbomlist> detailList = new ArrayList<>();
		for (VtuzxMap data : bomQuery){
			String billNo = VtuzxUtil.getString(data,"FBillNo");//用料清单单据编号
			String prdord = VtuzxUtil.getString(data,"FPrdOrgId.FName");//生产组织
			String workShop = VtuzxUtil.getString(data,"FWorkShopID.FName");//生产车间
			String unit = VtuzxUtil.getString(data,"FUnitID.FName");//单位
			String documentStatus = VtuzxUtil.getString(data,"FDocumentStatus");//单据状态
			String materialNo = VtuzxUtil.getString(data,"FMaterialID.FNumber");//物料编码
			String materialName = VtuzxUtil.getString(data,"FMaterialName");//物料名称
			String materialModel = VtuzxUtil.getString(data,"FMaterialModel");//规格
			String FNeedDate2 = VtuzxUtil.getString(data,"FNeedDate2");//需求日期(根据车间查询货品数量以及对应岗上仓库剩余数量)
			Date needDate = DateUtils.strToDate(FNeedDate2, "yyyy-MM-dd'T'HH:mm:ss");
			Double fQty = VtuzxUtil.getDouble(data,"FQty");//数量


			String FCreateDate = VtuzxUtil.getString(data,"FCreateDate");//创建日期
			Date createDate = DateUtils.strToDate(FCreateDate, "yyyy-MM-dd'T'HH:mm:ss");
			String FModifyDate = VtuzxUtil.getString(data,"FModifyDate");//修改日期
			Date modifyDate = DateUtils.strToDate(FModifyDate, "yyyy-MM-dd'T'HH:mm:ss");
			String taskBillNo = VtuzxUtil.getString(data,"FMOBillNO");//生产订单编号
			String entryId = VtuzxUtil.getString(data,"FSrcPPBOMID");//用料清单内码
			String childMaterialNo = VtuzxUtil.getString(data,"FMaterialID2.FNumber");//子项物料编码
			String childMaterialName = VtuzxUtil.getString(data,"FMaterialName1");//子项物料名称
			String childModle = VtuzxUtil.getString(data,"FMaterialModel1");//子项规格
			String childUnit = VtuzxUtil.getString(data,"FUnitID2.FName");//子项规格
			Double numerator = VtuzxUtil.getDouble(data,"FNumerator");//分子
			Double denominator = VtuzxUtil.getDouble(data,"FDenominator");//分母
			Double scrapQty = VtuzxUtil.getDouble(data,"FFixScrapQty");//固定损耗
			Double scrapRate = VtuzxUtil.getDouble(data,"FScrapRate");//变动损耗
			Double stdQty = VtuzxUtil.getDouble(data,"FStdQty");//标准用量
			Double needQty = VtuzxUtil.getDouble(data,"FNeedQty2");//标准用量
			Double mustQty = VtuzxUtil.getDouble(data,"FMustQty");//应发数量
			Double potCount = VtuzxUtil.getDouble(data,"F_DLMH_MGSL");//每锅数量
			Integer pot = VtuzxUtil.getInt(data,"F_DLMH_JGWC");//几锅完成
			Integer fbomEntryID = VtuzxUtil.getInt(data,"FBOMEntryID");//bom分录内码
			//先判断外层表数据是否存在,如果存在就先删除之前的重新添加,不存在就直接添加
			Proppbom proppbom = proppbomDao.selectOne(new QueryWrapper<Proppbom>().eq("billNo", billNo));
			if (null != proppbom){//如果存在就删除
				proppbomDao.delete(new QueryWrapper<Proppbom>().eq("billNo", billNo));
			}
			Proppbom ppbom = new Proppbom();
			ppbom.setBillNo(billNo);
			ppbom.setPrdorgId(prdord);
			ppbom.setWorkShop(workShop);
			ppbom.setFqty(fQty);
			ppbom.setUnit(unit);
			ppbom.setDocumentStatus(documentStatus);
			ppbom.setCreateDate(createDate);
			ppbom.setModifyDate(modifyDate);
			ppbom.setTaskBillNo(taskBillNo);
			ppbom.setFId(entryId);
			ppbom.setTaskMaterialNo(materialNo);
			ppbom.setTaskMaterialName(materialName);
			ppbom.setNeedDate(needDate);//需求日期
			ppbom.setTaskSpecification(materialModel);
			if (!proppbomList.contains(ppbom)){
				proppbomList.add(ppbom);
			}

			proppbomService.save(ppbom);
			//查询内层表数据判断是否存在
			Long detailCount = proppbomlistDao.selectCount(new QueryWrapper<Proppbomlist>().eq("billNo", billNo));
			//如果有数据删除重新添加
			if(detailCount > 0){
				proppbomlistDao.delete(new QueryWrapper<Proppbomlist>().eq("billNo", billNo));
			}
			Proppbomlist detail = new Proppbomlist();
			detail.setMaterialName(childMaterialName);
			detail.setMaterialNo(childMaterialNo);
			detail.setSpecification(childModle);
			detail.setNumerator(numerator);
			detail.setDenominator(denominator);
			detail.setUnit(childUnit);
			detail.setFixscrapqty(scrapQty);
			detail.setScraprate(scrapRate);
			detail.setStdQty(stdQty);
			detail.setNeedQty(needQty);
			detail.setMustQty(mustQty);
			detail.setBatch(pot);
			detail.setBatchQty(potCount);
			detail.setTaskBillNo(taskBillNo);
			detail.setBomEntryId(Long.valueOf(fbomEntryID));
			detail.setBillNo(billNo);
			if (!detailList.contains(detail)){
				detailList.add(detail);
			}
		}
		//添加数据

		proppbomlistService.saveBatch(detailList);
	}

	/**
	 * 计算员工的计件数量(传送带扫码方式)
	 * 总共是7个人干活,分成八份,接单冻的多剩下一份的1/3,装箱的多1/3的15%,入冷库的多1/3+1/3的85%
	 * @param userId
	 * @param userName
	 * @param taskBillNo
	 * @param size
	 * @param billNo
	 */
	private void calculateUserCount(Long userId, String userName, String taskBillNo, int size, String billNo){
		//先判断是几个人干活
		List<PrdTaskQty> taskQtyList = prdTaskQtyDao.selectList(new LambdaQueryWrapper<PrdTaskQty>()
				.eq(PrdTaskQty::getTaskBillNo, taskBillNo));
		int userSize = taskQtyList.size();//总共多少人干活
		double everyCount = size / (userSize + 1);//计算出每一份的数量
		double threeCount = everyCount / 3;//每一份的三分之一
		for (PrdTaskQty taskQty : taskQtyList){
			boolean isCold = taskQty.getIsColdStock();//是否冷库
			if(isCold){
				double count = everyCount + threeCount + threeCount * 0.85;
				taskQty.setWorkQty(Math.round(count));
				continue;
			}
			if (null != taskQty.getWorkType()){
				String workType = taskQty.getWorkType();
				if ("冷库".equals(workType)){
					double count = everyCount + threeCount;
					taskQty.setWorkQty(Math.round(count));
				} else if ("装箱".equals(workType)){
					double count = everyCount + threeCount * 0.15;
					taskQty.setWorkQty(Math.round(count));
				}
				continue;
			}
			//不是特殊工种的正常平分
			taskQty.setWorkQty(Math.round(everyCount));
		}
		prdTaskQtyService.saveOrUpdateBatch(taskQtyList);
	}
}